#ifndef VEC_3_H
#define VEC_3_H

#include <math.h>

class File;
struct Vec3
{
	Vec3() : m_x(0), m_y(0), m_z(0)
	{
	}

	Vec3(float x, float y, float z) : m_x(x), m_y(y), m_z(z)
	{
	}

	bool Load(File*);

	float x() const {return m_x; }
	float y() const {return m_y; }
	float z() const {return m_z; }

	Vec3& operator += (const Vec3& v)
	{
		m_x += v.m_x;
		m_y += v.m_y;
		m_z += v.m_z;
		return *this;
	}



	const bool operator == (const Vec3& v) const
	{
		return m_x == v.m_x
			&& m_y == v.m_y
			&& m_z == v.m_z;
	}

	Vec3 CrossProduct(const Vec3& Other)
	{
		Vec3 Result = *this;
		Vec3 Normal;

		Normal.m_x = Result.m_y * Other.m_z - Result.m_z * Other.m_y,
		Normal.m_y = Result.m_z * Other.m_x - Result.m_x * Other.m_z,
		Normal.m_z = Result.m_x * Other.m_y - Result.m_y * Other.m_x;
		
		return Normal;
	}

	float DotProduct(const Vec3& Other) const
	{
		return
			m_x * Other.m_x +
			m_y * Other.m_y +
			m_z * Other.m_z;
	}


	Vec3& operator -= (const Vec3& v)
	{
		m_x -= v.m_x;
		m_y -= v.m_y;
		m_z -= v.m_z;
		return *this;
	}

	Vec3& operator /= (float f)
	{
		float tempF = 1 / f;
		m_x *= tempF;
		m_y *= tempF;
		m_z *= tempF;
		return *this;
	}

	Vec3& operator*=(float f)
	{
		m_x *= f;
		m_y *= f;
		m_z *= f;
		return *this;
	}

	Vec3 operator+(const Vec3& v) const //operator + member version
	{
		Vec3 result = *this;
		result += v;
		return result;
	}

	Vec3 operator-(const Vec3& v) const //operator - member version
	{
		Vec3 result = *this;
		result -= v;
		return result;
	}

	float SquaredLength() const
	{
		return m_x * m_x + m_y * m_y + m_z * m_z;
	}

	float Length() const
	{
		return sqrt(SquaredLength());
	}

	Vec3 operator-() const
	{
		return Vec3(-m_x, -m_y, -m_z);
	}

	void Normalise()
	{
		float oneOverLength = 1.0f / Length();
		m_x *= oneOverLength;
		m_y *= oneOverLength;
		m_z *= oneOverLength;
	}

	float m_x, m_y, m_z;
};

inline Vec3 operator*(const Vec3& v, float f)
{
	Vec3 result = v;
	result *= f;
	return result;
}

inline float DotProduct(const Vec3& u, const Vec3& v)
{
	return u.x() * v.x() + u.y() * v.y() + u.z() * v.z();
}

inline Vec3 CrossProduct(const Vec3& u, const Vec3& v)
{
	return Vec3(
		u.y() * v.z() - u.z() * v.y(),
		u.z() * v.x() - u.x() * v.z(),
		u.x() * v.y() - u.y() * v.x() );
}

inline Vec3 Normalised(Vec3& v)
{
	Vec3 Tempvec = v;
	Tempvec.Normalise();
	return Tempvec;
}


inline float VecLength(Vec3& v)
{
	return v.Length();
}

typedef Vec3 Vec3f; //Vec3<float>

#endif